package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	"gitcode.com/eteam/sae.git/engine"
	"gitcode.com/eteam/sae.git/types"
	"github.com/chzyer/readline"
	"github.com/google/uuid"
)

type Client struct {
	servAddr string
	taskId   string
}

func NewClient(servAddr string) *Client {
	return &Client{
		servAddr: servAddr,
	}
}

func (c *Client) Run() error {
	rl, err := readline.New("user: > ")
	if err != nil {
		return err
	}
	for {
		line, err := rl.Readline()
		if err != nil {
			return err
		}
		err = c.process(line)
		if err != nil {
			return err
		}
	}
}

func (c *Client) process(textMsg string) error {
	parts := []types.Part{}
	if strings.HasPrefix(textMsg, "@file") {
		txtList := strings.SplitN(textMsg, " ", 2)
		if len(txtList) != 2 {
			return nil
		}
		parts = append(parts, types.Part{
			FilePart: &types.FilePart{
				FileName: "xx",
				FirlUri:  txtList[1],
			},
		})
	} else {
		parts = append(parts, types.Part{
			TextPart: &types.TextPart{
				Text: textMsg,
			},
		})
	}

	if c.taskId == "" {
		return c.createTask(parts)
	} else {
		return c.sendMessage(parts)
	}
}

func (c *Client) createTask(parts []types.Part) error {
	//获取技能ID
	msg := &types.Message{
		MessageId: uuid.NewString(),
		TimeStamp: time.Now().UnixMilli(),
		Role:      types.UserMessageRole,
		Parts:     parts,
		Kind:      types.MessageObjectKind,
	}
	reqBody, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	resp, err := http.Post(c.getServerUrl("/skill/guess"), "application/json", bytes.NewBuffer(reqBody))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	guessRes := &engine.GuessSkillResponse{}
	respData, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	err = json.Unmarshal(respData, guessRes)
	if err != nil {
		return err
	}
	//创建任务
	createReq := &engine.CreateTaskRequest{
		SkillId: guessRes.SkillId,
		Message: *msg,
	}
	reqBody, err = json.Marshal(createReq)
	if err != nil {
		return err
	}
	resp, err = http.Post(c.getServerUrl("/task/create"), "application/json", bytes.NewBuffer(reqBody))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	respData, err = io.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	createRes := &engine.CreateTaskResponse{}
	err = json.Unmarshal(respData, createRes)
	if err != nil {
		return err
	}
	c.taskId = createRes.TaskId
	//获取已有的消息
	c.outExistMessage()
	go c.watchEvent()
	return nil
}

func (c *Client) sendMessage(parts []types.Part) error {
	msg := &types.Message{
		MessageId: uuid.NewString(),
		TimeStamp: time.Now().UnixMilli(),
		Role:      types.UserMessageRole,
		Parts:     parts,
		Kind:      types.MessageObjectKind,
	}
	reqBody, err := json.Marshal(msg)
	if err != nil {
		return err
	}

	url := c.getServerUrl(fmt.Sprintf("/task/%s/message", c.taskId))
	_, err = http.Post(url, "application/json", bytes.NewBuffer(reqBody))
	if err != nil {
		return err
	}
	return nil
}

func (c *Client) getServerUrl(path string) string {
	return fmt.Sprintf("http://%s/api/v1%s", c.servAddr, path)
}

func (c *Client) watchEvent() {
	for {
		c.runWatchEvent()
	}
}

func (c *Client) runWatchEvent() {
	url := c.getServerUrl(fmt.Sprintf("/task/%s/event", c.taskId))
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

	scanner := bufio.NewScanner(resp.Body)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "data:") {
			c.outMessage(line[5:])
		}
	}
}

type KindWrap struct {
	Kind types.ObjectKind `json:"kind"`
}

func (c *Client) outMessage(jsonData string) {
	kindObj := &KindWrap{}
	err := json.Unmarshal([]byte(jsonData), kindObj)
	if err != nil {
		return
	}
	if kindObj.Kind == types.TaskStatusUpdateObjectKind {
		ev := &types.TaskStatusUpdateEvent{}
		json.Unmarshal([]byte(jsonData), ev)
		if ev.Status.State == types.TaskCompleted || ev.Status.State == types.TaskCanceled || ev.Status.State == types.TaskFailed || ev.Status.State == types.TaskRejected {
			os.Exit(0)
		}
	}
	if kindObj.Kind != types.MessageObjectKind {
		return
	}
	message := &types.Message{}
	err = json.Unmarshal([]byte(jsonData), message)
	if err != nil {
		return
	}
	fmt.Print("智能体: ")
	for _, part := range message.Parts {
		if part.TextPart != nil {
			fmt.Print(part.TextPart.Text)
		}
	}
	fmt.Println("")
}

func (c *Client) outExistMessage() {
	url := c.getServerUrl(fmt.Sprintf("/task/%s/data?withMessage=true&withArtifact=false&withFormDefine=false", c.taskId))
	resp, err := http.Get(url)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	task := &types.Task{}
	respData, err := io.ReadAll(resp.Body)
	if err != nil {
		return
	}

	err = json.Unmarshal(respData, task)
	if err != nil {
		return
	}
	for _, msg := range task.Messages {
		if msg.Role != types.AgentMessageRole {
			continue
		}
		fmt.Print("智能体: ")
		for _, part := range msg.Parts {
			if part.TextPart != nil {
				fmt.Print(part.TextPart.Text)
			}
		}
		fmt.Println("")
	}
}
